home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
machserver
/
1.098
/
raid
/
devRaid.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-27
|
15KB
|
510 lines
/*
* devRaid.c --
*
* This module implements the BlockDevice interface for
* RAID level 5 disk arrays.
* Assuming a minimum sector size of 512 bytes, RAID devices with an
* address space of upto 2^40 bytes (~1 terra byte) are supported by
* this driver.
*
* Copyright 1989 Regents of the University of California
* All rights reserved.
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/kernel/raid/RCS/devRaid.c,v 1.16 91/06/27 12:07:14 eklee Exp $ SPRITE (Berkeley)";
#endif /* not lint */
#include "sync.h"
#include <sprite.h>
#include <stdio.h>
#include <string.h>
#include "fs.h"
#include "dev.h"
/*
#include "devDiskLabel.h"
#include "devDiskStats.h"
*/
#include "devBlockDevice.h"
#include "devRaid.h"
#include "devRaidUtil.h"
#include "dev/raid.h"
#include "semaphore.h"
#include "devRaidLog.h"
#include "stdlib.h"
#include "dbg.h"
#include "devRaidProto.h"
static ReturnStatus StripeBlockIOProc();
static ReturnStatus RaidBlockIOProc();
static ReturnStatus ReleaseProc();
static ReturnStatus IOControlProc();
/*
* A RAID device must have a minor number between 0 and 31 inclusive.
*/
Raid raidArray[] = {
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 0")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 1")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 2")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 3")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 4")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 5")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 6")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 7")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 8")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 9")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 10")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 11")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 12")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 13")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 14")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 15")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 16")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 17")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 18")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 19")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 20")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 21")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 22")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 23")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 24")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 25")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 26")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 27")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 28")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 29")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 30")},
{RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 31")},
};
int numRaid = sizeof(raidArray)/sizeof(Raid);
/*
*----------------------------------------------------------------------
*
* DevRaidAttach --
*
* Attach a RAID logical device.
*
* Results:
* The DevBlockDeviceHandle of the device.
*
* Side effects:
* Modifies raidArray data structure.
*
*----------------------------------------------------------------------
*/
DevBlockDeviceHandle *
DevRaidAttach(devicePtr)
Fs_Device *devicePtr; /* The device to attach. */
{
RaidHandle *handlePtr;
Raid *raidPtr;
if ( devicePtr->unit >= numRaid ) {
return (DevBlockDeviceHandle *) NIL;
}
raidPtr = &raidArray[devicePtr->unit];
MASTER_LOCK(&raidPtr->mutex);
if ( raidPtr->state == RAID_INVALID ) {
raidPtr->state = RAID_ATTACHED;
MASTER_UNLOCK(&raidPtr->mutex);
#ifdef TESTING
Sync_CondInit(&raidPtr->waitExclusive);
Sync_CondInit(&raidPtr->waitNonExclusive);
#endif TESTING
Raid_InitStripeLocks();
InitDebugMem();
raidPtr->devicePtr = devicePtr;
Raid_Lock(raidPtr);
} else {
MASTER_UNLOCK(&raidPtr->mutex);
}
handlePtr = (RaidHandle *) malloc(sizeof(RaidHandle));
/*
* 'S' means data striping only, no parity.
* We use a different blockIOproc to support this function.
*/
if (raidPtr->parityConfig == 'S') {
handlePtr->blockHandle.blockIOProc = StripeBlockIOProc;
} else {
handlePtr->blockHandle.blockIOProc = RaidBlockIOProc;
}
handlePtr->blockHandle.releaseProc = ReleaseProc;
handlePtr->blockHandle.IOControlProc = IOControlProc;
handlePtr->blockHandle.minTransferUnit = 1 << raidPtr->logBytesPerSector;
handlePtr->blockHandle.maxTransferSize = RAID_MAX_XFER_SIZE;
handlePtr->devPtr = devicePtr;
handlePtr->raidPtr = &raidArray[devicePtr->unit];
return (DevBlockDeviceHandle *) handlePtr;
}
/*
*----------------------------------------------------------------------
*
* ReleaseProc --
*
* Block device release proc.
*
* Results:
* Return status.
*
* Side effects:
* Frees device handle.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
ReleaseProc(handlePtr)
RaidHandle *handlePtr; /* Handle pointer of device. */
{
/*
* Note: Only the handle is deallocated.
* The Raid data structures are never deallocated and stay around forever.
*/
free((char *) handlePtr);
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* IOControlProc --
*
* Do a special operation on a RAID device.
*
* Results:
* None.
*
* Side effects:
* Depends on operation.
*
*----------------------------------------------------------------------
*/
typedef struct {
Sema sema;
ReturnStatus status;
} IOCControl;
static void
iocDoneProc(iocCtrlPtr, status)
IOCControl *iocCtrlPtr;
ReturnStatus status;
{
printf("RAID:MSG:IOC completed.\n");
if (status != SUCCESS) {
printf("RAID:ERR:IOC failed.\n");
}
iocCtrlPtr->status = status;
UpSema(&iocCtrlPtr->sema);
}
static ReturnStatus
IOControlProc(handlePtr, ioctlPtr, replyPtr)
DevBlockDeviceHandle *handlePtr;
Fs_IOCParam *ioctlPtr;
Fs_IOReply *replyPtr;
{
static char *IObuf;
RaidHandle *raidHandlePtr = (RaidHandle *) handlePtr;
Raid *raidPtr = raidHandlePtr->raidPtr;
RaidIOCParam *raidIOCParamPtr = (RaidIOCParam *) ioctlPtr->inBuffer;
DevBlockDeviceRequest *requestPtr =
(DevBlockDeviceRequest *) ioctlPtr->inBuffer;
int col;
int row;
ReturnStatus status;
IOCControl iocCtrl;
if (raidIOCParamPtr == (RaidIOCParam *) NIL) {
printf("RAID:MSG:IOControlProc IOC == NIL\n");
return FAILURE;
}
col = raidIOCParamPtr->col;
row = raidIOCParamPtr->row;
bzero((char *) replyPtr, sizeof(Fs_IOReply));
switch(ioctlPtr->command) {
case IOC_DEV_RAID_PRINT:
if (raidPtr->state != RAID_VALID) {
return SUCCESS;
}
PrintRaid(raidPtr);
return SUCCESS;
case IOC_DEV_RAID_RECONFIG:
status = Raid_Configure(raidPtr, raidIOCParamPtr->buf);
return status;
case IOC_DEV_RAID_FAIL:
if (raidPtr->state != RAID_VALID) {
return FAILURE;
}
if (row < 0 || row >= raidPtr->numRow) {
printf("RAID:MSG:row=%d out of range on ioctl call", row);
return FAILURE;
}
if (col < 0 || col >= raidPtr->numCol) {
printf("RAID:MSG:col=%d out of range on ioctl call", col);
return FAILURE;
}
Raid_FailDisk(raidPtr, col, row, raidPtr->disk[col][row]->version);
return SUCCESS;
case IOC_DEV_RAID_REPLACE:
if (raidPtr->state != RAID_VALID) {
return FAILURE;
}
if (row < 0 || row >= raidPtr->numRow) {
printf("RAID:MSG:row=%d out of range on ioctl call", row);
return FAILURE;
}
if (col < 0 || col >= raidPtr->numCol) {
printf("RAID:MSG:col=%d out of range on ioctl call", col);
return FAILURE;
}
Raid_ReplaceDisk(raidPtr, col, row, raidPtr->disk[col][row]->version,
raidIOCParamPtr->type, raidIOCParamPtr->unit, 0);
return SUCCESS;
case IOC_DEV_RAID_HARDINIT:
if (raidPtr->state != RAID_VALID) {
return FAILURE;
}
InitSema(&iocCtrl.sema, "Raid HardInit", 0);
Raid_InitiateHardInit(raidPtr,
raidIOCParamPtr->startStripe, raidIOCParamPtr->numStripe,
iocDoneProc, (ClientData) &iocCtrl,
raidIOCParamPtr->ctrlData);
DownSema(&iocCtrl.sema);
return iocCtrl.status;
case IOC_DEV_RAID_PARITYCHECK:
if (raidPtr->state != RAID_VALID) {
return FAILURE;
}
InitSema(&iocCtrl.sema, "Raid ParityCheck", 0);
Raid_InitiateParityCheck(raidPtr,
raidIOCParamPtr->startStripe, raidIOCParamPtr->numStripe,
iocDoneProc, (ClientData) &iocCtrl,
raidIOCParamPtr->ctrlData);
DownSema(&iocCtrl.sema);
return iocCtrl.status;
case IOC_DEV_RAID_RECONSTRUCT:
if (raidPtr->state != RAID_VALID) {
return FAILURE;
}
InitSema(&iocCtrl.sema, "Raid Reconstruct", 0);
Raid_InitiateReconstruction(raidPtr, col, row,
raidPtr->disk[col][row]->version,
raidIOCParamPtr->numStripe, raidIOCParamPtr->uSec,
iocDoneProc, (ClientData) &iocCtrl,
raidIOCParamPtr->ctrlData);
DownSema(&iocCtrl.sema);
return iocCtrl.status;
case IOC_DEV_RAID_IO:
if (raidPtr->state != RAID_VALID) {
return FAILURE;
}
if (!IObuf) {
IObuf = (char *) malloc(1024*1024);
}
requestPtr->buffer = IObuf;
return Dev_BlockDeviceIOSync(handlePtr, requestPtr,
(int *)ioctlPtr->outBuffer);
case IOC_DEV_RAID_LOCK:
Raid_Lock(raidPtr);
return SUCCESS;
case IOC_DEV_RAID_UNLOCK:
Raid_Unlock(raidPtr);
return SUCCESS;
case IOC_DEV_RAID_SAVE_STATE:
if (raidPtr->state != RAID_VALID) {
return FAILURE;
}
status = Raid_SaveState(raidPtr);
if (status != SUCCESS) {
printf("RAID:MSG:Could not checkpoint state.\n");
}
return status;
case IOC_DEV_RAID_ENABLE_LOG:
Raid_EnableLog(raidPtr);
return SUCCESS;
case IOC_DEV_RAID_DISABLE_LOG:
Raid_DisableLog(raidPtr);
return SUCCESS;
case IOC_DEV_RAID_RESTORE_STATE:
raidPtr->logDev.type = raidIOCParamPtr->type;
raidPtr->logDev.unit = raidIOCParamPtr->unit;
raidPtr->logDevOffset = raidIOCParamPtr->startStripe;
/*
* Attach log device.
*/
raidPtr->logHandlePtr = Dev_BlockDeviceAttach(&raidPtr->logDev);
if (raidPtr->logHandlePtr == (DevBlockDeviceHandle *) NIL) {
printf("RAID:ERR:Could not attach log device %d %d\n",
raidPtr->logDev.type, raidPtr->logDev.unit);
return FAILURE;
}
status = Raid_RestoreState(raidPtr);
if (status != SUCCESS) {
printf("RAID:MSG:Could not restore state.\n");
}
return status;
default:
return SUCCESS;
}
}
/*
*----------------------------------------------------------------------
*
* StripeBlockIOProc --
* Perform block IO w/o parity, i.e. data striping only,
* on specified RAID device.
*
* Results:
* None.
*
* Side effects:
* The disk write, if operation == FS_WRITE.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
StripeBlockIOProc(handlePtr, requestPtr)
DevBlockDeviceHandle *handlePtr;
DevBlockDeviceRequest *requestPtr;
{
RaidHandle *raidHandlePtr;
Raid *raidPtr;
unsigned firstSector;
unsigned nthSector;
unsigned numSector;
raidHandlePtr = (RaidHandle *) handlePtr;
raidPtr = raidHandlePtr->raidPtr;
/*
* Check if operation valid.
*/
if (!((requestPtr->operation == FS_READ) ||
(requestPtr->operation == FS_WRITE))) {
panic("Unknown operation %d in RAID blockIOProc.\n",
requestPtr->operation);
return DEV_INVALID_ARG;
}
/*
* Convert byte addresses to sector addresses.
*/
firstSector = (requestPtr->startAddress >> raidPtr->logBytesPerSector) |
(requestPtr->startAddrHigh<<(BITS_PER_ADDR-raidPtr->logBytesPerSector));
numSector = requestPtr->bufferLen >> raidPtr->logBytesPerSector;
nthSector = firstSector + numSector;
/*
* Check that addresses are within the range supported by the device.
*/
if ( firstSector >= raidPtr->numSector ) {
requestPtr->doneProc(requestPtr, FAILURE, 0);
return SUCCESS;
}
/*
* Prevent overruns.
*/
if ( nthSector > raidPtr->numSector ) {
nthSector = raidPtr->numSector;
}
Raid_InitiateSimpleStripeIOs(raidPtr, requestPtr->operation,
firstSector, nthSector, requestPtr->buffer,
requestPtr->doneProc, (ClientData) requestPtr,
requestPtr->ctrlData[0]);
return SUCCESS;
}
/*
*----------------------------------------------------------------------
*
* RaidBlockIOProc --
*
* Perform block IO (w/ parity) on specified RAID device.
*
* Results:
* None.
*
* Side effects:
* The disk write, if operation == FS_WRITE.
*
*----------------------------------------------------------------------
*/
static ReturnStatus
RaidBlockIOProc(handlePtr, requestPtr)
DevBlockDeviceHandle *handlePtr;
DevBlockDeviceRequest *requestPtr;
{
RaidHandle *raidHandlePtr;
Raid *raidPtr;
unsigned firstSector;
unsigned nthSector;
unsigned numSector;
raidHandlePtr = (RaidHandle *) handlePtr;
raidPtr = raidHandlePtr->raidPtr;
/*
* Check if operation valid.
*/
if (!((requestPtr->operation == FS_READ) ||
(requestPtr->operation == FS_WRITE))) {
panic("Unknown operation %d in RAID blockIOProc.\n",
requestPtr->operation);
return DEV_INVALID_ARG;
}
/*
* Convert byte addresses to sector addresses.
*/
firstSector = (requestPtr->startAddress >> raidPtr->logBytesPerSector) |
(requestPtr->startAddrHigh<<(BITS_PER_ADDR-raidPtr->logBytesPerSector));
numSector = requestPtr->bufferLen >> raidPtr->logBytesPerSector;
nthSector = firstSector + numSector;
/*
* Check that addresses are within the range supported by the device.
*/
if ( firstSector >= raidPtr->numSector ) {
requestPtr->doneProc(requestPtr, FAILURE, 0);
return SUCCESS;
}
/*
* Prevent overruns.
*/
if ( nthSector > raidPtr->numSector ) {
nthSector = raidPtr->numSector;
}
Raid_InitiateStripeIOs(raidPtr, requestPtr->operation,
firstSector, nthSector, requestPtr->buffer,
requestPtr->doneProc, (ClientData) requestPtr,
requestPtr->ctrlData[0]);
return SUCCESS;
}